--[[
Most handlers there are dirty and hackish and should better be implemented in
the addon themselves.

They all register a CONFIGMODE_CALLBACKS with the same as the addon except
when such callback already exists. So it will NOT override addon-defined
callback.

If the addon is not yet loaded but could be loaded later, a listener
is set up to wait until the addon is loaded.
]]

CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {}

-- Simple helper: return true if the addon exist and can be loaded
local function IsLoadable(name)
	local exists, _, _, enabled, loadable = GetAddOnInfo(name)
	return exists and enabled and loadable and true
end

local demos = {}

-- ag_UnitFrames
function demos.ag_UnitFrames()
	if CONFIGMODE_CALLBACKS.ag_UnitFrames then return end
	local aUF = LibStub("AceAddon-3.0"):GetAddon("ag_UnitFrames")
	local wasLocked
	function CONFIGMODE_CALLBACKS.ag_UnitFrames(action, mode)
		if action == 'GETMODES' then
			return 'party', 'raid'
		end
		LoadAddOn('ag_Options')
		if not aUF.UpdateSetupMode then
			return
		end
		if action == 'ON' then
			wasLocked = aUF.db.profile.Locked
			aUF.db.profile.Locked = false
			if mode == "raid" then
				aUF:UpdateSetupMode("raid")
			else
				aUF:UpdateSetupMode("party")
			end
		elseif action == 'OFF' then
			aUF:UpdateSetupMode('off')
			if wasLocked then
				aUF.db.profile.Locked = true
				wasLocked = nil
			end
		end
	end
end


-- Quartz
function demos.Quartz()
	if CONFIGMODE_CALLBACKS.Quartz then return end
	local Quartz = _G.Quartz
	local qmodules = {
		Player = 'lock',
		Focus = 'lock',
		Target = 'lock',
		Pet = 'lock',
		Mirror = 'mirrorlock',
	}
	local toggled = {}
	function CONFIGMODE_CALLBACKS.Quartz(action)
		local options = Quartz.options.args
		if action == 'ON' then
			for module,optName in pairs(qmodules) do
				local opt = options[module] and options[module].args and options[module].args[optName]
				if opt and opt.get() then
					toggled[module] = optName
					opt.set(false)
				end
			end
		elseif action == 'OFF' then
			for module,optName in pairs(toggled) do
				local opt = options[module] and options[module].args and options[module].args[optName]
				opt.set(true)
			end
			wipe(toggled)
		end
	end
end

-- Cork
function demos.Cork()
	if CONFIGMODE_CALLBACKS.Cork then return end
	local Cork = _G.Cork
	local wasAnchorHidden
	function CONFIGMODE_CALLBACKS.Cork(action)
		if action == 'ON' and not Cork.anchor:IsShown() then
			wasAnchorHidden = true
			Cork.anchor:Show()
		elseif action =='OFF' and wasAnchorHidden then
			Cork.anchor:Hide()
			wasAnchorHidden = nil
		end
	end
end

-- Grid
function demos.Grid()
	if CONFIGMODE_CALLBACKS.Grid then return end
	local wasLocked
	function CONFIGMODE_CALLBACKS.Grid(action)
		if action == 'ON' and GridLayout.options.args.lock.get() then
			wasLocked = true
			GridLayout.options.args.lock.set(false)
		elseif action == 'OFF' and wasLocked then
			GridLayout.options.args.lock.set(true)
			wasLocked = nil
		end
	end
end

-- BigWigs
function	demos.BigWigs()
	if CONFIGMODE_CALLBACKS['BigWigs'] then return end
	local barModule, messageModule, proxModule

	local function GetModules()
		barModule = barModule or BigWigs:HasModule('Bars 2') and BigWigs:GetModule('Bars 2')
		messageModule = messageModule or BigWigs:HasModule('Messages') and BigWigs:GetModule('Messages')
		proxModule = proxModule or BigWigs:HasModule('Proximity') and BigWigs:GetModule('Proximity')
		return barModule and messageModule and proxModule
	end

	local toggled
	local wasMessageAnchorHidden

	local function handler(action)
		if action == "ON" then
			wasMessageAnchorHidden = not messageModule.consoleOptions.set("anchor")
			toggled = true
			messageModule.consoleOptions.set("anchor", true)
			barModule:ShowAnchors()
			proxModule:TestProximity()
		elseif action == "OFF" then
			if wasMessageAnchorHidden then
				messageModule.consoleOptions.set("anchor", false)
				wasMessageAnchorHidden = nil
			end
			if toggled then
				barModule:ShowAnchors()
				proxModule:CloseProximity()
				toggled	= nil
			end
		end
	end

	if GetModules() then
		CONFIGMODE_CALLBACKS['BigWigs'] = handler
	else
		CONFIGMODE_CALLBACKS['BigWigs'] = function(action)
			if action == 'ON' then
				LoadAddOn('BigWigs_Plugins')
				LoadAddOn('BigWigs_Extras')
				if GetModules() then
					CONFIGMODE_CALLBACKS['BigWigs'] = handler
					handler(action)
				else
					CONFIGMODE_CALLBACKS['BigWigs'] = nil
				end
			end
		end
	end
end


-- Gladius
function demos.Gladius()
	if CONFIGMODE_CALLBACKS.Gladius then return end
	local wasLocked
	function CONFIGMODE_CALLBACKS.Gladius(action, mode)
		if action == 'ON' then
			wasLocked = Gladius.db.profile.locked
			Gladius.db.profile.locked = false

			local bracket = tonumber(tostring(mode):sub(1,1)) or 5
			if bracket ~= Gladius.currentBracket then
				Gladius:ToggleFrame(bracket)
			else
				Gladius:UpdateFrame()
			end
		elseif action == 'OFF' then
			if wasLocked then
				Gladius.db.profile.locked = true
				wasLocked = false
			end
			Gladius:HideFrame()

		elseif action == "GETMODES" then
			return "5vs5", "3vs3", "2vs2"
		end
	end
end

-- Omen
function demos.Omen()
	if CONFIGMODE_CALLBACKS.Omen then return end
	local lockedInfo = {"Locked"}
	local opts
	local wasTestModeDisabled
	local wasLocked
	function CONFIGMODE_CALLBACKS.Omen(action)
		if not opts then
			if not Omen.Options then
				Omen.GenerateOptions()
			end
			opts = Omen.Options.args.General.args
		end
		if action == 'ON' then
			wasTestModeDisabled = not opts.TestMode.get()
			wasLocked = Omen.Options.get(lockedInfo)
			opts.TestMode.set(nil, true)
			opts.Locked.set(lockedInfo, false)
			Omen:Toggle(true)
		elseif action == 'OFF' then
			if wasTestModeDisabled then
				opts.TestMode.set(nil, false)
				wasTestModeDisabled = nil
			end
			if wasLocked then
				opts.Locked.set(lockedInfo, true)
				wasLocked = nil
			end
			Omen:Toggle(false)
		end

	end
end

local eventFrame = CreateFrame("Frame")
eventFrame:SetScript('OnEvent', function(self, event, ...) self[event](self, event, ...) end)

function eventFrame:VARIABLES_LOADED()
	self:UnregisterEvent('VARIABLES_LOADED')
	self.VARIABLES_LOADED =  nil

	CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {}

	-- Immediatly register handlers for already loaded addons
	local pending
	for name, callback in pairs(demos) do
		if IsAddOnLoaded(name) then
			local ok, err = pcall(callback)
			if not ok then geterrorhandler()(err) end
		elseif IsLoadable(name) then
			if not pending then
				pending = {}
			end
			pending[name:lower()] = callback
		end
	end
	demos = nil

	if pending then
		-- Listen to ADDON_LOADED to register pending handlers
		self:RegisterEvent('ADDON_LOADED')
		function self:ADDON_LOADED(_, name)
			local callback = pending[name:lower()]
			if callback then
				local ok, err = pcall(callback)
				if not ok then geterrorhandler()(err) end
				pending[name:lower()] = nil
			end
			if not next(pending) then
				-- Nothing more to do, clean up
				pending = nil
				self:UnregisterEvent('ADDON_LOADED')
				self.ADDON_LOADDED = nil
			end
		end
	end
end

if IsLoggedIn() then
	eventFrame:VARIABLES_LOADED()
else
	eventFrame:RegisterEvent('VARIABLES_LOADED')
end

--[[RangeDisplay
function demos.RangeDisplay()
	if CONFIGMODE_CALLBACKS.RangeDisplay then return end
	local RD = LibStub("AceAddon-3.0"):GetAddon("RangeDisplay")
	local wasLocked
	function CONFIGMODE_CALLBACKS.RangeDisplay(action, mode)
		if action == 'ON' then
			wasLocked = RD.db.profile.Locked
			RD.db.profile.locked = false
			RangeDisplay:unlock()

		elseif action == 'OFF' then
			RangeDisplay:unlock()
			if wasLocked then
				RD.db.profile.Locked = true
				wasLocked = nil
			end
		end
	end
end

-- Bartender4
function demos.Bartender4()
	if CONFIGMODE_CALLBACKS.Bartender4 then return end
	local Bartender4 = LibStub("AceAddon-3.0"):GetAddon("Bartender4")
	local wasLocked
	function CONFIGMODE_CALLBACKS.Bartender4(action)
		if action == 'ON' then
			Bartender4.Locked = false
			wasLocked = true
			Bartender4.Unlock()
		elseif action =='OFF' and wasAnchorHidden then
			Bartender4.Locked = true
			Bartender4.lock()
			wasLocked = nil
		end
	end
end]]